package WizardTD;

import WizardTD.board.Board;
import WizardTD.board.FuncButton;
import WizardTD.board.ManaProcessBar;
import WizardTD.constant.Constant;
import WizardTD.constant.ImageConstant;
import WizardTD.element.MonsterBox;
import WizardTD.element.Fireball;
import WizardTD.element.Tower;
import WizardTD.enums.ButtonEnum;
import javazoom.jl.decoder.JavaLayerException;
import processing.core.PApplet;
import processing.data.JSONObject;
import processing.event.MouseEvent;
import javazoom.jl.player.advanced.*;

import ddf.minim.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class App extends PApplet {

    /**
     * 单元长度
     */
    public static final int CELLSIZE = 32;
    /**
     * 边栏宽度
     */
    public static final int SIDEBAR = 120;
    /**
     * 顶栏宽度
     */
    public static final int TOPBAR = 40;
    /**
     * 主单元格数量
     */
    public static final int BOARD_WIDTH = 20;
    /**
     * 地图宽度
     */

    public static int WIDTH = CELLSIZE * BOARD_WIDTH + SIDEBAR;
    /**
     * 地图长度
     */
    public static int HEIGHT = BOARD_WIDTH * CELLSIZE + TOPBAR;

    /**
     * 刷新率FPS
     */
    public static final int FPS = 60;
    /**
     * 配置文件路径
     */
    public static final String configPath = "config.json";

    /**
     * 塔标志
     */
    public static boolean towerFlag = false;
    /**
     * 塔的列表
     */
    public static List<Tower> towers = new ArrayList<>();
    /**
     * 火球列表
     */
    public static List<Fireball> fireballs = new ArrayList<>();
    /**
     * 移除火球列表
     */
    public static List<Fireball> removeFireballs = new ArrayList<>();

    /**
     * 是否暂停
     */
    public static boolean isPause = false;
    /**
     * 怪物盒子
     */
    public static MonsterBox monsterBox;

    /**
     * 背景
     */
    public static Board board;

    /**
     * 速度
     */
    public static int speed = 1;


    /**
     * 波数
     */
    public static int waveNum = 0;

    /**
     * 数据构造类
     */
    private DataConstruct dataConstruct;
    /**
     * 元素绘图类
     */
    private ElementDraw elementDraw;

    private Minim minim;
    private AudioPlayer player;

    // Feel free to add any additional methods or attributes you want. Please put classes in different files.

    /**
     * Initialise the setting of the window size.
     */
    @Override
    public void settings() {
        size(WIDTH, HEIGHT);
    }

    /**
     * Load all resources such as images. Initialise the elements such as the player, enemies and map elements.
     */
    @Override
    public void setup() {
        minim = new Minim(this);
        player = minim.loadFile("background.mp3");
        player.play();

        initImage();
        initConfig();
        App.board = new Board(this, Constant.layout);
        dataConstruct = new DataConstruct(this);
        dataConstruct.generateData();
        monsterBox = new MonsterBox(dataConstruct, this);
        elementDraw = new ElementDraw(dataConstruct.getLevelAndWaveConfig(), this, dataConstruct);
        frameRate(FPS);
        // Load images during setup
        // Eg:


    }

    /**
     * 初始化配置
     */
    private void initConfig() {
        JSONObject config = loadJSONObject(App.configPath);
        Constant.initialTowerRange = config.getFloat("initial_tower_range");
        Constant.initialTowerFiringSpeed = config.getFloat("initial_tower_firing_speed");
        Constant.initialTowerDamage = config.getFloat("initial_tower_damage");
        Constant.layout = config.getString("layout");
        Constant.initialMana = config.getFloat("initial_mana");
        Constant.initialManaCap = config.getFloat("initial_mana_cap");
        Constant.initialManaGainedPerSecond = config.getFloat("initial_mana_gained_per_second");
        Constant.manaPoolSpellInitialCost = config.getFloat("mana_pool_spell_initial_cost");
        Constant.manaPoolSpellCostIncreasePerUse = config.getFloat("mana_pool_spell_cost_increase_per_use");
        Constant.manaPoolSpellCapMultiplier = config.getFloat("mana_pool_spell_cap_multiplier");
        Constant.manaPoolSpellManaGainedMultiplier = config.getFloat("mana_pool_spell_mana_gained_multiplier");
    }

    /**
     * 初始化图片
     */
    private void initImage() {
        ImageConstant.tower0 = loadImage("src/main/resources/WizardTD/tower0.png");
        ImageConstant.tower1 = loadImage("src/main/resources/WizardTD/tower1.png");
        ImageConstant.tower2 = loadImage("src/main/resources/WizardTD/tower2.png");
        ImageConstant.path0 = loadImage("src/main/resources/WizardTD/path0.png");
        ImageConstant.path1 = loadImage("src/main/resources/WizardTD/path1.png");
        ImageConstant.path2 = loadImage("src/main/resources/WizardTD/path2.png");
        ImageConstant.path3 = loadImage("src/main/resources/WizardTD/path3.png");
        ImageConstant.shrub = loadImage("src/main/resources/WizardTD/shrub.png");
        ImageConstant.grass = loadImage("src/main/resources/WizardTD/grass.png");
        ImageConstant.wizardHouse = loadImage("src/main/resources/WizardTD/wizard_house.png");
        ImageConstant.worm = loadImage("src/main/resources/WizardTD/worm.png");
        ImageConstant.gremlin = loadImage("src/main/resources/WizardTD/gremlin.png");
        ImageConstant.gremlin1 = loadImage("src/main/resources/WizardTD/gremlin1.png");
        ImageConstant.gremlin2 = loadImage("src/main/resources/WizardTD/gremlin2.png");
        ImageConstant.gremlin3 = loadImage("src/main/resources/WizardTD/gremlin3.png");
        ImageConstant.gremlin4 = loadImage("src/main/resources/WizardTD/gremlin4.png");
        ImageConstant.gremlin5 = loadImage("src/main/resources/WizardTD/gremlin5.png");
    }

    /**
     * Receive key pressed signal from the keyboard.
     */
    @Override
    public void keyPressed() {

    }

    /**
     * Receive key released signal from the keyboard.
     */
    @Override
    public void keyReleased() {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    /*@Override
    public void mouseDragged(MouseEvent e) {

    }*/

    /**
     * 鼠标单机事件
     */
    @Override
    public void mouseClicked() {

        //点击按钮
        FuncButton funcButton = board.isFuncButton(mouseX, mouseY);
        if (funcButton != null) {
            funcButton.click();
        }
        //点击tower
        Tower tower = board.getTower(mouseX, mouseY);
        if (tower != null) {

            ManaProcessBar mana = board.getManaProcessBar();
            //calculate cast
            int castMana = 0;
            if (board.getChoiceButtons().contains(ButtonEnum.U1)) {
                castMana += 20 + 10 * tower.levelMap.getOrDefault("range", 0);
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U2)) {
                castMana += 20 + 10 * tower.levelMap.getOrDefault("range", 0);
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U3)) {
                castMana += 20 + 10 * tower.levelMap.getOrDefault("range", 0);
            }
            if (mana.getCurrentMana() < castMana) return;

            //upgrade
            if (board.getChoiceButtons().contains(ButtonEnum.U1)) {
                board.getChoiceButtons().remove(ButtonEnum.U1);
                tower.upgrade("range");
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U2)) {
                board.getChoiceButtons().remove(ButtonEnum.U2);
                tower.upgrade("speed");
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U3)) {
                board.getChoiceButtons().remove(ButtonEnum.U3);
                tower.upgrade("damage");
            }
            tower.setChoose(true);
        }

        //点击草地放置tower
        if (board.isGrass(mouseX, mouseY, 32)
                && board.getChoiceButtons().contains(ButtonEnum.T)
                && tower == null) {

            ManaProcessBar mana = board.getManaProcessBar();
            //calculate cast
            int castMana = 20;
            if (board.getChoiceButtons().contains(ButtonEnum.U1)) {
                castMana += 20;
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U2)) {
                castMana += 20;
            }
            if (board.getChoiceButtons().contains(ButtonEnum.U3)) {
                castMana += 20;
            }
            if (mana.getCurrentMana() <= castMana) return;

            board.getChoiceButtons().remove(ButtonEnum.T);
            Tower newTower = new Tower(mouseX - 16, mouseY - 16);
            if (board.getChoiceButtons().remove(ButtonEnum.U1)) {
                newTower.upgrade("range");
            }
            if (board.getChoiceButtons().remove(ButtonEnum.U2)) {
                newTower.upgrade("speed");
            }
            if (board.getChoiceButtons().remove(ButtonEnum.U3)) {
                newTower.upgrade("damage");
            }
            towers.add(newTower);
        }


    }


    /**
     * Draw all elements in the game by current frame.
     */
    @Override
    public void draw() {
        if (!App.isPause) {
            elementDraw.startGame(dataConstruct);
        }
    }

    public static void main(String[] args) {
        PApplet.main("WizardTD.App");
    }


}
